/**
 * createAuthor: jaden.liu
 * createTime: 2020/02/27
 */
(function ($) {
  $.fn.Flowdesign = function (options) {
    var _canvas = $(this);

    /**
     * 节点与连接的名字必须唯一。生成后台模型,在走向判断以及节点查找的时候，由名字(name)决定。
     * 通过默认属性中的名字,结合guid生成一个名字，这样的名字看起来更加有意义,便于查看
     */
    var guid = 1;

    /**
     * 该id用于标识整个流程节点的唯一性，通常设置为元素的id。在instance.connect的时候，使用的id
     * @type {number}
     */
    var lastProcessId = 1;

    var processPrefix = "process-";

    var defaults = {
      fnRepeat: function () {
        console.log("步骤连接重复");
      },
      fnClick: function () {
        console.log("单击");
      },
      fnDbClick: function () {
        console.log("双击");
      },
      fnConnectionClick: function () {
        console.log("连接线单击");
      },
      createCanvasMenus: true,
      canvasMenus: {
        menus: {
          "save": "暂存",
          "clear": "清空",
          "refresh": "重置"
        },
        "save": function () {
          console.log("暂存");
        },
        "clear": function () {
          console.log("清空");
        },
        "refresh": function () {// 刷新
          console.log("重置");
        }
      },
      createConnectionMenus: true,
      connectionMenus: {
        menus: {
          "delete": "删除",
          "attribute": "属性"
        },
        "delete": function (connection) {
          console.log("删除")
        },
        "attribute": function (connection) {
          console.log("属性")
        }
      },
      createProcessMenus: true,
      processMenus: {
        menus: {
          "delete": "删除",
          "attribute": "属性"
        },
        "delete": function (process) {
          console.log("删除")
        },
        "attribute": function (process) {
          console.log("属性")
        }
      },
      paintStyle: {
        stroke: "gray", // vue高版本属性
        strokeWidth: 3,// vue高版本属性
        strokeStyle: "gray",
        lineWidth: 3
      },
      hoverPaintStyle: {
        stroke: "#216477",// vue高版本属性
        strokeWidth: 3,// vue高版本属性
        strokeStyle: "#216477",
        lineWidth: 3
      }
    };

    // var top
    // var left
    var lastProcessId = 0;
    var activeConnection = null;
    var activeProcess = null;

    // 替换默认配置
    $.each(options, function (i, val) {
      if (typeof val == "object" && defaults[i]) {
        $.extend(defaults[i], val);
      } else {
        defaults[i] = val;
      }
    });

    // 初始化菜单 start
    var createMenu = function (menuUl, menus, func) {
      $(menuUl).addClass("dropdown-menu").attr("role", "menu").attr(
        "aria-labelledby", "dropdownMenu");
      document.body.appendChild(menuUl);
      $.each(menus, function (action, name) {
        var menuLI = document.createElement("li");
        var a = document.createElement("a");
        menuLI.appendChild(a);
        menuUl.appendChild(menuLI);
        var _a = $(a);
        _a.attr("href", "#").html(name);
        a.onclick = function (e) {
          func(action);
          e.preventDefault();
        };
      });
    }

    if (defaults.createCanvasMenus) {
      var canvasMenuUl = document.createElement("ul");
      createMenu(canvasMenuUl, defaults.canvasMenus.menus, function (action) {
        var func = eval("defaults.canvasMenus." + action);
        func(1111);
        $(canvasMenuUl).stop().fadeOut(200);
      });
      _canvas.append(canvasMenuUl);
    }
    if (defaults.createConnectionMenus) {
      var connectionMenuUl = document.createElement("ul");
      createMenu(connectionMenuUl, defaults.connectionMenus.menus, function (action) {
        var func = eval("defaults.connectionMenus." + action);
        func(activeConnection);
        $(connectionMenuUl).stop().fadeOut(200);
      });
      _canvas.append(connectionMenuUl);
    }
    if (defaults.createProcessMenus) {
      var processMenuUl = document.createElement("ul");
      createMenu(processMenuUl, defaults.processMenus.menus,
        function (action) {
          var func = eval("defaults.processMenus." + action);
          func(activeProcess);
          $(processMenuUl).stop().fadeOut(200);
        });
      _canvas.append(processMenuUl);
    }

    var showMenu = function (menuUI, event) {
      event.preventDefault();
      hideAllMenu();
      var pageX = event.pageX - _canvas.offset().left + _canvas.scrollLeft();
      var pageY = event.pageY - _canvas.offset().top + _canvas.scrollTop() - 20;
      $(menuUI).css({
        left: pageX + "px",
        top: pageY + "px"
      }).stop().fadeIn(500);
    };

    var hideAllMenu = function () {
      $(canvasMenuUl).stop().fadeOut(200);
      $(connectionMenuUl).stop().fadeOut(200);
      $(processMenuUl).stop().fadeOut(200);
    };

    _canvas.on("contextmenu", function (event) { // 绑定画布右键菜单
      if (event.target == this) {
        //showMenu(canvasMenuUl, event); //禁止画布右键
        return;
      }
      if (event.target.tagName == "path") {
        activeConnection = event.target.parentNode._jsPlumb;
        showMenu(connectionMenuUl, event);
        return;
      }

      var fixedTarget = $(event.target).closest(".process-step").get(0);//修正task节点的孩子元素点击
      if (fixedTarget.classList.contains("process-step")) {
        activeProcess = fixedTarget;
        showMenu(processMenuUl, event);
        return;
      }
    });

    // 单击隐藏右键菜单
    _canvas.on("click", function (event) {
      hideAllMenu();
    });

    // 初始化菜单 end
    //浏览器兼容
    /*var nav = navigator.userAgent.toLowerCase();
    var isie = nav.indexOf('msie') > -1;
    if (isie) { //ie9以下，用VML画图
      if (nav.substring(nav.indexOf("MSIE") + 5, nav.indexOf("MSIE") + 8) < '9.0') {
        jsPlumb.setRenderMode(jsplumb.jsPlumb.VML);
      }
    } else { //其他浏览器用SVG
      jsPlumb.setRenderMode(jsplumb.jsPlumb.SVG);
    }*/

    var instance = jsPlumb.getInstance({
      //修复 拖拽触发click的问题 http://stackoverflow.com/questions/24277114/onclick-property-conflict-with-jqueryui-drag-and-drop
      DragOptions: {
        cursor: "pointer",
        delay: 500,
        start: function (event, ui) {
          $(event.el).attr("drag", true);
        },
        stop: function (event) {
          /* var $drag = $(event.el);
           $drag.css({
           top: event.pos[1] - 16
           });
           instance.repaintEverything();*/
        }
      },
      Anchor: "Continuous", // 锚点位置
      Endpoint: ["Dot", {radius: 7}],
      EndpointStyle: {// 点样式
        width: 14,
        height: 14,
        fill: '#94c14f',// vue高版本属性
        fillStyle: "#94c14f"
      },
      PaintStyle: defaults.paintStyle,
      HoverPaintStyle: defaults.hoverPaintStyle, // 箭头
      //连线的类型，流程图(Flowchart)、贝塞尔曲线(Bezier)等
      Connector: ["Flowchart", {
        stub: [10, 10],
        gap: 5,
        cornerRadius: 5,
        alwaysRespectStubs: true
      }],
      ConnectionOverlays: [["Arrow", {
        location: 1,
        width: 11,
        length: 11
      }]],
      Container: _canvas
    });

    var createProcess = function (type, style, attrCache) {
      var process = {
        type: type,
        style: style,
        source: false,
        sourceMaxConnection: -1,
        target: false,
        targetMaxConnection: -1,
        attrCache: attrCache
      };
      intiProcess(process);
    };

    var intiProcess = function (process) {
      var nodeDefaultClass = "process-icon process-step process-node";
      // 根据节点类型设置连接点
      process.source = true;
      process.target = true;
      switch (process.type) {
        case "startevent-timer":
        case "startevent-none":
          process.target = false;
          process.sourceMaxConnection = 1;
          break;
        case "endevent-none":
        case "endevent-cancel":
          process.source = false;
          break;
        case "gateway-exclusive":// 唯一
          break;
        case "gateway-inclusive":// 包含
          break;
        case "gateway-parallel":// 并行
          break;
        case "task"://普通用户任务
          nodeDefaultClass = nodeDefaultClass + " user-task ";
          break;
        default:
          break;
      }

      var processDiv = document.createElement("div");
      var _processDiv = $(processDiv);
      _processDiv.css({top: process.left, left: process.top, position: 'absolute'});

      _processDiv.attr("process-type", process.type).attr("style",
        process.style).addClass(nodeDefaultClass);

      //节点增加数据缓存
      var defaultAttr = defaultComponentAttr[process.type];
      var attrCache = process.attrCache;
      if (!attrCache) {
        attrCache = $.extend(true, {}, defaultAttr, {"name": (defaultAttr["name"] + guid++)});
        _processDiv.data("attrCache", attrCache);
      } else {
        _processDiv.data("attrCache", $.extend(true, {}, attrCache));
      }

      //name 和id都必须唯一
      _processDiv.attr("id", processPrefix + lastProcessId++);//用name作为唯一id
      _processDiv.attr("name", attrCache["name"]);//把那么附加上去。后面通过name来找到对应的id,然后进行连接

      instance.getContainer().appendChild(processDiv);
      instance.draggable(processDiv);

      var timeout = null;

      _processDiv.on("click", function () {
        if ($(this).attr("drag") == "true") {//如果是drag触发的click,则不进行处理
          $(this).removeAttr("drag");
          return;
        }
        // 点击或双击事件,这里进行了一个单击事件延迟，因为同时绑定了双击事件
        clearTimeout(timeout);
        /**http://stackoverflow.com/questions/2130241/pass-correct-this-context-to-settimeout-callback*/
        var _this = this;
        timeout = setTimeout(function () {
          defaults.fnClick.apply(_this, arguments)
        }, 100);
      }).on("dblclick", function () {
        clearTimeout(timeout);
        defaults.fnDbClick.apply(this, arguments);
      });

      //增加节点显示文本
      if (process.type == "task") {
        var $textElem = $("<div>", {
          "class": "task-inner-text"
        });
        $textElem.text(process.attrCache["displayName"]);
        _processDiv.append($textElem);
      }

      if (process.source) {
        var ep = document.createElement("div");
        $(ep).addClass("ep");
        _processDiv.append(ep);

        makeSource(processDiv, process.sourceMaxConnection);
      }
      if (process.target) {
        makeTarget(processDiv, process.targetMaxConnection);
      }
    };
    instance.bind("click", function (connection, originalEvent) {
      defaults.fnConnectionClick.apply(this, arguments)
    });

    var makeSource = function (processDiv, maxConnections) {
      instance.makeSource(processDiv, {
        filter: ".ep",
        maxConnections: maxConnections,
        onMaxConnections: function (info, e) {
          alert("超过最大连接数:" + info.maxConnections);
        }
      });
    };

    var makeTarget = function (processDiv, maxConnections) {
      instance.makeTarget(processDiv, {
        allowLoopback: true,
        maxConnections: maxConnections,
        onMaxConnections: function (info, e) {
          alert("超过最大连接数:" + info.maxConnections);
        },
        beforeDrop: function (params) {// 判断是否重复连接
          var sourceId = params.sourceId;
          var targetId = params.targetId;
          if (sourceId == targetId) {//禁止自己和自己相连接
            return false;
          }
          var connectionId = params.connection.id;
          var connections = instance.getConnections({
            source: sourceId,
            target: targetId
          });
          if (connections.length > 0) {
            for (var i = 0; i < connections.length; i++) {
              if (connections[i].id != connectionId) {
                defaults.fnRepeat();
                return false;
              }
            }
          }
          return true;
        }
      });
    };

    var refresh = function (processData) {
      var nodesInfo = processData["nodesInfo"];
      for (var key in nodesInfo) {
        var process = nodesInfo[key];
        createProcess(process.type, process.style, process["attrCache"]);
      }

      var connectionsInfo = processData["connectionsInfo"];
      for (var key in connectionsInfo) {
        var connectionInfo = connectionsInfo[key];
        var sourceNameSelector = "div[name=" + connectionInfo["from"] + "]";
        var targetNameSelector = "div[name=" + connectionInfo["to"] + "]";
        var sourceId = $(document).find(sourceNameSelector).attr("id");
        var targetId = $(document).find(targetNameSelector).attr("id");
        var connection = instance.connect({
          source: sourceId,
          target: targetId,
          label: connectionInfo["attrCache"]["displayName"]
        });
        if (connection.getLabelOverlay()) {
          connection.getLabelOverlay().addClass("connection-label");
        }
        connection.setData(connectionInfo["attrCache"]);
      }

      instance.repaintEverything();
      instance.fire("refresh", instance);
    };

    var refreshConnectionDefaultName = function (connection) {
      var data = connection.getData();
      data["name"] = data.name || (defaultComponentAttr["connection"]["name"] + guid++);
      connection.setData(data);
    };

    var refreshNodeDefaultName = function (node) {
      var $node = $(node);
      var attrCache = $node.data("attrCache");
      var defaultValue = defaultComponentAttr[$node.attr("process-type")];
      if (!attrCache || !attrCache["name"]) {//如果缓存数据不存在或者名字不存在，都的设置名字
        $node.data("attrCache", $.extend(true, {}, attrCache, {name: defaultValue["name"] + guid++}));
      }
    };

    /**
     * 如果连接或者是节点没有唯一的名称,则赋值。
     */
    var refreshConnectionsNodeDefaultName = function () {
      $("#canvas").find(".process-step").each(function (i, node) {
        refreshNodeDefaultName(node);
      });

      $.each(instance.getAllConnections(), function (i, connection) {
        refreshConnectionDefaultName(connection);
      });
    };

    function getNodeType(connectionRelation) {
      return $('#canvas').find('[name=' + (connectionRelation && connectionRelation.from) + ']').attr('process-type')
    }

    function getConnection(sourceTaskName, targetTaskName) {
      var $canvas = $('#canvas');
      var sourceNameSelector = "div[name=" + sourceTaskName + "]";
      var targetNameSelector = "div[name=" + targetTaskName + "]";
      var sourceId = $canvas.find(sourceNameSelector).attr("id");
      var targetId = $canvas.find(targetNameSelector).attr("id");
      return instance.connect({
        source: sourceId,
        target: targetId
      });
    }

    function setConnectionColor(connectionRelation) {
      connectionRelation.connection.setPaintStyle(window.flowDetailConnStyle);
    }

    function walkThroughConnection(connectionsRelation, approvalDetails, targetTaskNames) {
      if (targetTaskNames.length == 1) {//不是并行任务
        var targetTaskName = targetTaskNames[0];
        var sourceTaskName = approvalDetails[0].taskName;//上个任务

        var connectionRelation = _.findWhere(connectionsRelation, {from: sourceTaskName, to: targetTaskName});
        if (connectionRelation) {//如果存在说明是直接相连
          setConnectionColor(connectionRelation);
        } else {
          //逆向搜索
          connectionRelation = _.findWhere(connectionsRelation, {to: targetTaskName});

          var nodeType = getNodeType(connectionRelation);
          switch (nodeType) {
            case 'gateway-fork':
              var connectionRelation1 = _.findWhere(connectionsRelation, {to: connectionRelation.from});//向上搜索一次
              var connectionRelation2 = _.findWhere(connectionsRelation, {to: connectionRelation1.from});//向上搜索一次
              if (connectionRelation2 && getNodeType(connectionRelation2) == 'gateway-exclusive') {//如果是判断节点
                setConnectionColor(connectionRelation);
                setConnectionColor(connectionRelation1);
                setConnectionColor(connectionRelation2);
              } else {
                setConnectionColor(connectionRelation);
                setConnectionColor(connectionRelation1);
              }
              break;
            case 'gateway-join'://如果是合并节点，那么前面的都已近执行完了
              //循环设置颜色
              connectionsRelation = _.where(connectionsRelation, {to: connectionRelation.from});
              for (var i = 0; i < connectionsRelation.length; i++) {
                setConnectionColor(connectionsRelation[i]);
              }
              setConnectionColor(connectionRelation);
              break;
            default://剩下的就是驳回并且连线不存在
              var connection = getConnection(sourceTaskName, targetTaskName);
              connection.setPaintStyle(window.flowDetailConnStyle);
          }
        }
      } else {
      }
    }

    function dateFormat(str) {
      if (str) {
        //str = String(str);
        if (str.length == 8) {
          return str.substr(0, 4) + '-' + str.substr(4, 2) + '-' + str.substr(6, 2);
        }
      }
      return str;
    };

    function datetimeFormat(str) {
      if (str) {
        str = String(str);
        var strs = str.split(' ');
        if (strs.length == 2) {
          return dateFormat(strs[0]) + ' ' + dateFormat(strs[1]);
        }
      }
      return str;
    };

    function getTimeDifference(dateStr1, dateStr2) {
      var date1 = new Date(Date.parse(datetimeFormat(dateStr1).replace(/-/g, "/")));
      var date2 = new Date(Date.parse(datetimeFormat(dateStr2).replace(/-/g, "/")));
      var ms = (date2.getTime() - date1.getTime()); // / 24 / 3600 / 1000;

      var day1 = Math.floor(ms / 24 / 3600 / 1000),
        hh1 = Math.floor((ms / 3600 / 1000) % 24),
        mm1 = Math.floor((ms / 1000 / 60) % 60),
        ss1 = Math.floor((ms / 1000) % 60);
      return {
        day: day1,
        HH: hh1,
        mm: mm1,
        ss: ss1
      };
    };

    function convertTaskDetail(detail) {
      var taskDetail = {};
      if (!detail.result) {//开始申请
        taskDetail.duration = '-';
        taskDetail.showResult = '提交流程申请';
        taskDetail.opinion = '-';
      } else {
        var diff = getTimeDifference(datetimeFormat(detail.createDate + ' ' + detail.createTime), datetimeFormat(detail.finishDate + ' ' + detail.finishTime));
        taskDetail.duration = diff.day + '天' + diff.HH + '时' + diff.mm + '分' + diff.ss + '秒';
        taskDetail.opinion = detail.opinion;
      }
      taskDetail.approvalDatetime = datetimeFormat(detail.finishDate + ' ' + detail.finishTime);
      taskDetail.showResult = taskDetail.showResult || detail.resultText || window.processStatus[detail.result];
      taskDetail.username = detail.approvalUser || detail.applyUser;
      return taskDetail;
    }

    // 审批页面，只需要当前需要审批的一个节点变色即可
    function handleBackground(approvalDetails, allTaskNames, currentTaskNames, isRefuse) {
      var $canvas = $('#canvas');
      //移除所有当前节点
      for (var i = 0; i < currentTaskNames.length; i++) {
        delete approvalDetails[currentTaskNames[i]];
      }

      //完成节点变色
      var finishTaskNames = _.pluck(approvalDetails, 'taskName');
      _.each(finishTaskNames, function (ele) {
        var selector = '[name=' + ele + ']';
        $canvas.find(selector).css('background-color', window.finishBg);
      });

      //未完成节点变色
      var unFinishTaskNames = _.difference(allTaskNames, finishTaskNames);
      _.each(unFinishTaskNames, function (ele) {
        var selector = '[name=' + ele + ']';
        $canvas.find(selector).css('background-color', window.unFinishBg);
      });

      //当前成节点变色
      if (isRefuse) {
        var selector = '[name=' + approvalDetails[0].taskName + ']';
        $canvas.find(selector).css('background-color', window.refuseBg);
      } else {
        for (var i = 0; i < currentTaskNames.length; i++) {
          var selector = '[name=' + currentTaskNames[i] + ']';
          $canvas.find(selector).css('background-color', window.currentBg);
        }
      }
    }

    function popoverTaskDetail(approvalDetail, currentTaskNames) {
      var $canvas = $("#canvas");
      $canvas.find('[process-type=task]').each(function (index, ele) {
        $(ele).popover({
          trigger: 'hover',
          placement: 'bottom',
          title: "",
          html: true,
          delay: {"show": 500, "hide": 100},
          container: 'body',
          content: function () {
            var taskName = $(this).attr('name');
            var items = _.where(approvalDetail, {taskName: taskName});

            /**
             *  1. 如果有审核历史,获取最近的一个，用于展示信息
             *  2. 并且不是当前任务
             */
            if (items.length != 0 && !_.contains(currentTaskNames, taskName)) {
              var taskDetail = convertTaskDetail(items[0]);
              // return Tools.getHtmlFromHandlebar('#task-approval-detail-template', taskDetail);
            } else {
              // return Tools.getHtmlFromHandlebar('#task-approval-no-detail-template');
            }
            return ''
          },
          viewport: '#canvas'
        });
      });
    }

    function handleRejectConnectionColor(connectionsRelation, sourceTaskName, targetTaskName) {
      var connectionRelation = _.findWhere(connectionsRelation, {from: sourceTaskName, to: targetTaskName});
      //如果存在连接，直接设置颜色即可
      if (connectionRelation) {
        setConnectionColor(connectionRelation);
      } else {//不存在先连线，再设置颜色
        getConnection(sourceTaskName, targetTaskName).setPaintStyle(window.flowDetailConnStyle);
      }
    }

    /**
     * 处理节点的背景色即可
     */
    function handleStartProcess(requestSupportParams) {
      $.ajax({
        // conf/queryAllTaskName.json
        url: requestSupportParams.url + "?processName=" + requestSupportParams.processName,
        type: 'POST',
        success: function (data) {
          data = JSON.parse(data);
          if (data.status == '200') {
            var $canvas = $('#canvas');
            var result = data.data;
            for (var i = 0; i < result.length; i++) {
              var selector = '[name=' + result[i] + ']';
              if (i == 0) {
                $canvas.find(selector).css('background-color', window.currentBg);
              } else {
                $canvas.find(selector).css('background-color', window.unFinishBg);
              }
            }
            instance.repaintEverything();
          } else {
            alert(data.message);
          }
        }
      });
    }

    var Flowdesign = {
      addProcess: function (type, style) {
        // TODO 验证增加节点类型
        var attrCache = $.extend(true, {}, defaultComponentAttr[type], {"name": defaultComponentAttr[type]["name"] + guid++});
        createProcess(type, style, attrCache);
      },
      deleteProcess: function (process) {
        instance.detachAllConnections(process.id);
        instance.removeAllEndpoints(process.id);
        $(process).remove();
      },
      connect: function (sourceId, targetId) {

      },
      deleteConnection: function (connect) {
        instance.detach(connect);
      },
      getProcessInfo: function () {
        /***数据格式
         * processData = {
         * 		nodesInfo: {
         * 			"${node_name}":{
         * 				type: "type"
         * 				style: "left: 638px; top: 31px;",
         * 				attrCache: {
         * 				}
         * 	  	      }
         * 		},
         * 		connectionsInfo:{
         *			"transition_name":{
         *				from:"node_name",
         *				to:	 "node_name",
         *				attrCache: {
         *
         *				}
         *			}
         * 		}
         * }
         */
        var processData = {};
        var nodesInfo = {}, connectionsInfo = {};
        processData["nodesInfo"] = nodesInfo;
        processData["connectionsInfo"] = connectionsInfo;

        _canvas
          .find("div.process-step")
          .each(function () {
            var $this = $(this);
            var attrCache = $this.data("attrCache");//这里必须要保证name唯一, 否则会出现覆盖的情况
            var nodeKey = attrCache["name"];
            var nodeValue = {
              "type": $this.attr("process-type"),
              "style": $this.attr("style"),
              "attrCache": attrCache
            };
            nodesInfo[nodeKey] = nodeValue;
          });

        var autoKeyIndex = 1;
        var autoKeyPrefix = "autoConnection";
        var existKey = [];
        $.each(instance.getAllConnections(), function (i, connection) {
          var connectionAttrCache = connection.getData();
          var key = connectionAttrCache["name"];
          //如果key不存在(即没有被用户点击过)，或者是key已经存在,则自动生成
          if (!key || $.inArray(key, existKey) != -1) {
            key = autoKeyPrefix + autoKeyIndex++;
          }
          existKey.push(key);
          connectionsInfo[key] = {
            "from": $(connection["source"]).data("attrCache")["name"],
            "to": $(connection["target"]).data("attrCache")["name"],
            "attrCache": connectionAttrCache
          };
        });
        /**
         var processData = [];
         var connectData = {};
         $.each(instance.getAllConnections(),
         function(i, connection) {
							var pId = $(connection.source).attr(
								"process-id");
							if (!connectDatas[pId]) {
								connectDatas[pId] = [];
							}
							var connectionInfo = {};
							if (connection.getData().id) {
								connectionInfo = connection.getData();
							} else {
								var _target = $(connection.target);
								connectionInfo["target"] = parseInt(_target
									.attr("process-id"));
								connectionInfo["type"] = "n";
							}
							connectDatas[pId].push(connectionInfo);
						});
         */
        /**
         _canvas
         .find("div.process-step")
         .each(
         function(i) {
										if ($(this).attr("id")) {
											var processData = {};
											processData["id"] = parseInt($(this)
													.attr("process-id"));
											processData["type"] = $(this).attr(
													"process-type");
											processData["connections"] = connectDatas[processData.id];
											processData["style"] = $(this)
													.attr("style");
											processData.push(processData);
										}
									});
         */
        return JSON.stringify(processData);
      },
      getProcessTaskNames: function () {
        var taskNames = [];
        _canvas
          .find("div.process-step")
          .each(function () {
            var $this = $(this);
            var attrCache = $this.data("attrCache");
            if ($this.attr("process-type") == 'task') {
              var name = attrCache.name;
              var displayName = attrCache.displayName;
              if (!!name && !!displayName) {
                taskNames.push({
                  id: name,
                  name: displayName
                })
              }
            }
          });
        return taskNames;
      },
      clear: function () {
        instance.detachEveryConnection();
        instance.deleteEveryEndpoint();
        instance.repaintEverything();
        _canvas.find("div.process-step").each(function (i) {
          $(this).remove();
        });
        return true;
      },
      refresh: function (processData) {
        refresh(processData);
        refreshConnectionsNodeDefaultName();
        return true;
      },
      // 显示详情
      refreshDetail: function (processData, requestSupportParams) {
        var allTaskNames = [];
        // 画节点
        var nodesInfo = processData["nodesInfo"];
        for (var key in nodesInfo) {
          var node = nodesInfo[key];
          var attrCache = node["attrCache"];
          var nodeDefaultClass = "process-icon process-step process-node";

          if (node.type == "task") {
            nodeDefaultClass = nodeDefaultClass + " user-task ";
            allTaskNames.push(attrCache.name);
          }
          var processDiv = document.createElement("div");
          var _processDiv = $(processDiv);
          _processDiv.css({top: node.left, left: node.top, position: 'absolute'});
          _processDiv.attr("process-type", node.type).attr("style", node.style).addClass(nodeDefaultClass);
          _processDiv.offset({top: 20, left: 20});// 偏移
          // 添加节点
          instance.getContainer().appendChild(processDiv);
          //增加节点显示文本
          if (node.type == "task") {
            var $textElem = $("<div>", {
              "class": "task-inner-text"
            });
            $textElem.text(attrCache["displayName"]);
            _processDiv.append($textElem);
          }
          _processDiv.attr("id", processPrefix + lastProcessId++);//用name作为唯一id
          _processDiv.attr("name", attrCache["name"]);//把那么附加上去。后面通过name来找到对应的id,然后进行连接
          makeSource(processDiv, -1);
          makeTarget(processDiv, -1);
        }

        var connectionsInfo = processData["connectionsInfo"];
        // 存储连续之间的关系
        var connectionsRelation = [];
        for (var key in connectionsInfo) {
          var connectionInfo = connectionsInfo[key];
          var from = connectionInfo["from"];
          var to = connectionInfo["to"];

          var sourceNameSelector = "div[name=" + from + "]";
          var targetNameSelector = "div[name=" + to + "]";
          var sourceId = $(document).find(sourceNameSelector).attr("id");
          var targetId = $(document).find(targetNameSelector).attr("id");
          // 创建连接线
          var connection = instance.connect({
            source: sourceId,
            target: targetId,
            label: connectionInfo["attrCache"]["displayName"]
          });
          if (connection.getLabelOverlay()) {
            connection.getLabelOverlay().addClass("connection-label");
          }
          connectionsRelation.push({
            from: from,
            to: to,
            connection: connection
          });
        }
        //设置流程名
        var $diagramName = $('#diagramName');
        $diagramName.find('.process-name').text(processData.displayName);
        //这个只在流程实例中显示
        if (requestSupportParams.page == 'hisCompleteProcessInstance') {
          $diagramName.find('.process-status').text('(' + window.processStatus[requestSupportParams.status] + ')');
        }

        //如果是自定义页面，不再继续向下执行
        if (requestSupportParams.method == 'start') {
          handleStartProcess();
          return false;
        }
        //是否在审批页面
        var isApprovalPage = requestSupportParams.approvalPage == 'true';
        //实例是否还在运行中
        var runningStatus = requestSupportParams.status;
        /**
         * 在审批页面(路径颜色，只对驳回处理)
         * 1. 当前节点不用查询，高亮当前节点和其它审批节点的背景色，并且审批详情popover不存在
         * 2. 如果是驳回节点， 如果节点不存在，则先连线，再设置颜色。存在直接设置颜色
         */
        var currentTaskNames = [];
        if (isApprovalPage) {
          currentTaskNames = [requestSupportParams.taskName];
          //防止IE缓存问题
          $.ajax({
            url: requestSupportParams.url + "?processId=" + requestSupportParams.processId + "&processInstanceId=" + requestSupportParams.processInstanceId + "&timestamp=" + (new Date().getTime()),
            success: function (data) {
              data = JSON.parse(data);
              if (data.status == '200') {
                var approvalDetails = data.data;
                //处理审批、未审批的背景、当前任务的背景
                handleBackground(approvalDetails, allTaskNames, currentTaskNames);
                //悬浮显示任务详情,当前任务不应该有详情
                popoverTaskDetail(approvalDetails, currentTaskNames);
                //设置驳回节点的颜色
                if (approvalDetails[0].result == processStatusConstant.reject) {
                  handleRejectConnectionColor(connectionsRelation, approvalDetails[0].taskName, requestSupportParams.taskName)
                }
                instance.repaintEverything();
              } else {
                alert(data.message);
              }
            }
          });
        } else {
          //只有流程在运行中，才需要额外的查询, 防止并行的情况
          if (runningStatus == window.processStatusConstant.running) {
            //查询当前流程的最新节点，并高亮,由于存在并行任务，所以要去查询
            $.ajax({
              url: requestSupportParams.url + "?processInstanceId=" + requestSupportParams.processInstanceId,
              type: 'POST',
              success: function (data) {
                data = JSON.parse(data);
                if (data.status == '200') {
                  var currentTaskNames = [];
                  for (var i = 0; i < data.data.length; i++) {
                    var taskName = data.data[i].name;
                    currentTaskNames.push(taskName);
                  }
                  //最后才修改路径颜色和背景色，请求有开销
                  $.ajax({
                    url: requestSupportParams.url + "?processId=" + requestSupportParams.processId + "&processInstanceId=" + requestSupportParams.processInstanceId + "&timestamp=" + (new Date().getTime()),
                    type: 'POST',
                    success: function (data) {
                      data = JSON.parse(data);
                      if (data.status == '200') {
                        var approvalDetails = data.data;
                        //处理审批、未审批的背景、当前任务的背景
                        handleBackground(approvalDetails, allTaskNames, currentTaskNames);
                        //悬浮显示任务详情,当前任务不应该有详情
                        popoverTaskDetail(approvalDetails, currentTaskNames);
                        instance.repaintEverything();
                      } else {
                        alert(data.message);
                      }
                    }
                  });
                }
              }
            });
          } else {
            var url = requestSupportParams.url + "?processId=" + requestSupportParams.processId + "&processInstanceId=" + requestSupportParams.processInstanceId + "&timestamp=" + (new Date().getTime())
            $.ajax({
              url: url,
              type: 'POST',
              success: function (data) {
                data = JSON.parse(data);
                if (data.status == '200') {
                  //是否是拒绝
                  var isRefuse = (runningStatus == window.processStatusConstant.refuse);
                  var approvalDetails = data.data;
                  //处理审批、未审批的背景、当前任务的背景
                  handleBackground(approvalDetails, allTaskNames, currentTaskNames, isRefuse);
                  //悬浮显示任务详情,当前任务不应该有详情
                  popoverTaskDetail(approvalDetails, currentTaskNames);
                  instance.repaintEverything();
                } else {
                  alert(data.message);
                }
              }
            });
          }
        }
        return true;
      },
      getSelectedConnection: function () {
        var result = null;
        $.each(instance.getAllConnections(),
          function (i, connection) {
            if (connection.getPaintStyle().strokeStyle != defaults.paintStyle.strokeStyle) {
              result = connection;
              return;
            }
          });
        return result;
      },
      refreshConnectionDefaultname: function (connection) {
        refreshConnectionDefaultName(connection);
      },
      guid: guid
    };
    return Flowdesign;
  };
})(jQuery);
